# -*- coding: utf-8 -*-
import requests
import re
import time

def main():
    # 请求头，模拟浏览器访问
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    }

    # 基础URL
    base_url = 'https://book.douban.com/top250'

    print('开始爬取豆瓣读书Top250完整榜单...')

    all_books_html = []  # 存储所有页面的HTML
    total_books = 0      # 统计总书籍数量

    # 循环爬取10页数据（每页25本，共250本）
    for page in range(10):
        start = page * 25
        if start == 0:
            url = base_url
        else:
            url = f'{base_url}?start={start}'

        print(f'\n正在爬取第 {page + 1} 页 (URL: {url})...')

        try:
            # 发送GET请求
            response = requests.get(url, headers=headers, timeout=10)
            response.encoding = 'utf-8'

            if response.status_code == 200:
                # 保存当前页面的HTML
                all_books_html.append(f'=== 第 {page + 1} 页 ===\n')
                all_books_html.append(response.text)
                all_books_html.append('\n\n')

                # 解析当前页面的书籍数据
                page_books = parse_books(response.text, page + 1)
                total_books += page_books

                print(f'第 {page + 1} 页爬取完成，获得 {page_books} 本书')

                # 延时避免请求过快
                time.sleep(1)
            else:
                print(f'第 {page + 1} 页请求失败，状态码: {response.status_code}')
                break

        except Exception as e:
            print(f'第 {page + 1} 页爬取失败: {e}')
            break

    # 保存所有HTML到文件
    with open('douban_books_html.txt', 'w', encoding='utf-8') as f:
        f.writelines(all_books_html)
    print(f'\n所有HTML内容已保存到 douban_books_html.txt')
    print(f'爬取完成！总共获得 {total_books} 本书')

    # 保存正则表达式分析到文件
    save_regex_analysis()

def parse_books(html_content, page_num=1):
    print(f'\n第 {page_num} 页：开始解析书籍数据...')

    # 书籍列表的正则表达式
    book_pattern = r'<tr class="item">.*?</tr>'
    books = re.findall(book_pattern, html_content, re.DOTALL)

    print(f'第 {page_num} 页找到 {len(books)} 本书')

    book_count = 0
    for i, book_html in enumerate(books, 1):
        # 计算全局书籍编号
        global_book_num = (page_num - 1) * 25 + i

        print(f'\n===== 第 {global_book_num} 本书 (第{page_num}页第{i}本) =====')

        # 提取书名
        title_match = re.search(r'<a href="[^"]*".*?title="([^"]*)"', book_html)
        title = title_match.group(1) if title_match else '未找到书名'

        # 提取作者和出版社信息
        info_match = re.search(r'<p class="pl">(.*?)</p>', book_html)
        info = info_match.group(1) if info_match else '未找到出版信息'

        # 提取评分
        rating_match = re.search(r'<span class="rating_nums">([^<]*)</span>', book_html)
        rating = rating_match.group(1) if rating_match else '未找到评分'

        # 提取评价人数
        rating_count_match = re.search(r'<span class="pl">\(\s*(\d+)人评价\s*\)</span>', book_html, re.DOTALL)
        rating_count = rating_count_match.group(1) if rating_count_match else '未找到评价人数'

        # 提取书籍简介
        quote_match = re.search(r'<span class="inq">(.*?)</span>', book_html)
        quote = quote_match.group(1) if quote_match else '无简介'

        # 提取书籍链接
        link_match = re.search(r'<a href="([^"]*)".*?title="[^"]*"', book_html)
        link = link_match.group(1) if link_match else '未找到链接'

        print(f'书名: {title}')
        print(f'出版信息: {info}')
        print(f'评分: {rating}')
        print(f'评价人数: {rating_count}')
        print(f'简介: {quote}')
        print(f'链接: {link}')

        book_count += 1

    print(f'第 {page_num} 页解析完成，共解析 {book_count} 本书')
    return book_count

def save_regex_analysis():
    analysis_content = r'''

========== 正则表达式分析 ==========

1. 书籍列表匹配:
   <tr class="item">.*?</tr>
   - 匹配每个书籍所在的完整表格行
   - 使用re.DOTALL标志使.匹配换行符

2. 书名提取:
   <a href="[^"]*".*?title="([^"]*)"
   - 匹配链接标签中的title属性
   - 捕获组1: 书名

3. 出版信息提取:
   <p class="pl">(.*?)</p>
   - 匹配class为pl的p标签内容
   - 捕获组1: 作者、出版社、价格等信息

4. 评分提取:
   <span class="rating_nums">([^<]*)</span>
   - 匹评分类
   - 捕获组1: 评分数值

5. 评价人数提取:
   <span class="pl">\\(\\s*(\\d+)人评价\\s*\\)</span>
   - 匹配评价人数格式，考虑换行和空格
   - 捕获组1: 评价人数
   - 使用re.DOTALL标志处理多行情况

6. 书籍简介提取:
   <span class="inq">(.*?)</span>
   - 匹配class为inq的span标签
   - 捕获组1: 书籍简介

7. 书籍链接提取:
   <a href="([^"]*)".*?title="[^"]*"
   - 匹配链接的href属性
   - 捕获组1: 书籍详情页链接

注意事项:
- 豆瓣HTML结构相对统一，但仍需考虑部分书籍可能缺少某些元素
- 使用非贪婪匹配.*?避免过度匹配
- 部分书籍可能没有简介(inq标签)
- 评价人数信息可能跨多行显示，需要使用re.DOTALL标志
'''

    with open('douban_books_html.txt', 'a', encoding='utf-8') as f:
        f.write(analysis_content)

    print('\n正则表达式分析已追加保存到 douban_books_html.txt')

if __name__ == '__main__':
    main()